package com.drzhang.movieticketpicker.view;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.DrawFilter;
import android.graphics.Paint;
import android.graphics.PaintFlagsDrawFilter;
import android.graphics.Path;
import android.graphics.RectF;
import android.os.Handler;
import android.os.Message;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.View;

import com.drzhang.movieticketpicker.R;

import java.util.Timer;
import java.util.TimerTask;

import static com.drzhang.movieticketpicker.view.DynamicWave.dipToPx;

public class AudioPlayView extends View {
    private static final int DEFAULT_MIN_WIDTH = 500;
    private Context mContext;

    private Paint mCirclePaint;
    private Paint timePaint;
    private Paint paint1;
    private Paint paint2;
    private Paint paint3;
    private Path path1;
    private Path path2;
    private Path path3;
    private RectF rectF;

    private int waveHeight = 100;
    private int waveHeight1 = 80;
    private int waveHeight3 = 90;
    private float offset = 0f;//偏移量

    private int width;
    private int height;
    private int tempWidth = 0;
    private int waveAmplitude;
    private int highLevel;
    private int countdownTime = 10;



    // 波纹颜色
    private static final int WAVE_PAINT_COLOR = 0x880000aa;
    // y = Asin(wx+b)+h
    private static final float STRETCH_FACTOR_A = 20;
    private static final int OFFSET_Y = 0;
    // 第一条水波移动速度
    private static final int TRANSLATE_X_SPEED_ONE = 7;
    // 第二条水波移动速度
    private static final int TRANSLATE_X_SPEED_TWO = 5;
    private float mCycleFactorW;

    private int mTotalWidth, mTotalHeight;
    private float[] mYPositions;
    private float[] mResetOneYPositions;
    private float[] mResetTwoYPositions;
    private int mXOffsetSpeedOne;
    private int mXOffsetSpeedTwo;
    private int mXOneOffset;
    private int mXTwoOffset;

    private Paint mWavePaint;
    private DrawFilter mDrawFilter;



    private Timer timeTimer = new Timer(true);
    private Timer curveTimer = new Timer(true);
    private TimerTask timeTask;
    private TimerTask curveTask;
    public final static int MSG_UPDATE_TIME = 100;
    public final static int MSG_UPDATE_CURVE = 300;
    private boolean isPause = false;

    Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            if (msg.what == MSG_UPDATE_TIME) {
                countdownTime--;
                if (countdownTime == 0) {
                    timeTask.cancel();
                    curveTask.cancel();
                }
                postInvalidate();
            }else if (msg.what == MSG_UPDATE_CURVE){
                if (path1 == null){
                    return;
                }
//                drawWave();
            }

        }
    };

    public AudioPlayView(Context context) {
        this(context, null);
    }

    public AudioPlayView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);

    }

    public AudioPlayView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initView(context);
    }

    private void initView(Context context) {
        this.mContext = context;

        timeTask = new TimerTask() {
            public void run() {
                if (isPause){
                    return;
                }
                Message msg = new Message();
                msg.what = MSG_UPDATE_TIME;
                mHandler.sendMessage(msg);
            }
        };
        curveTask = new TimerTask() {
            @Override
            public void run() {
                if (isPause){
                    return;
                }
                Message msg = new Message();
                msg.what = MSG_UPDATE_CURVE;
                mHandler.sendMessage(msg);
            }
        };

        mCirclePaint = new Paint();
        mCirclePaint.setAntiAlias(true);
        mCirclePaint.setStyle(Paint.Style.STROKE);

        timePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        timePaint.setTextSize(dip2px(mContext, 26));
        timePaint.setColor(Color.WHITE);
        timePaint.setTextAlign(Paint.Align.CENTER);



        // 将dp转化为px，用于控制不同分辨率上移动速度基本一致
        mXOffsetSpeedOne = dipToPx(context, TRANSLATE_X_SPEED_ONE);
        mXOffsetSpeedTwo = dipToPx(context, TRANSLATE_X_SPEED_TWO);

        // 初始绘制波纹的画笔
        mWavePaint = new Paint();
        // 去除画笔锯齿
        mWavePaint.setAntiAlias(true);
        // 设置风格为实线
        mWavePaint.setStyle(Paint.Style.FILL);
        // 设置画笔颜色
        mWavePaint.setColor(WAVE_PAINT_COLOR);
        mDrawFilter = new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);

    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        setMeasuredDimension(measure(widthMeasureSpec), measure(heightMeasureSpec));
        initParameters();
    }

    private void initParameters() {
        width = getMeasuredWidth();
        height = getMeasuredHeight();
        rectF = new RectF(5, 5, width - 5, height - 5);

        paint1 = new Paint();
        paint1.setAntiAlias(true);
        paint1.setColor(mContext.getResources().getColor(R.color.color1));

        paint2 = new Paint();
        paint2.setAntiAlias(true);
        paint2.setColor(mContext.getResources().getColor(R.color.color2));

        paint3 = new Paint();
        paint3.setAntiAlias(true);
        paint3.setColor(mContext.getResources().getColor(R.color.color3));

        path1 = new Path();
        path2 = new Path();
        path3 = new Path();
        waveAmplitude = 20;
        highLevel = (int) (height * (0.5) + waveAmplitude);
    }

    private int measure(int origin) {
        int result = DEFAULT_MIN_WIDTH;
        int specMode = MeasureSpec.getMode(origin);
        int specSize = MeasureSpec.getSize(origin);
        if (specMode == MeasureSpec.EXACTLY) {
            result = specSize;
        } else {
            if (specMode == MeasureSpec.AT_MOST) {
                result = Math.min(result, specSize);
            }
        }
        return result;
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        // 记录下view的宽高
        mTotalWidth = w;
        mTotalHeight = h;
        // 用于保存原始波纹的y值
        mYPositions = new float[mTotalWidth];
        // 用于保存波纹一的y值
        mResetOneYPositions = new float[mTotalWidth];
        // 用于保存波纹二的y值
        mResetTwoYPositions = new float[mTotalWidth];

        // 将周期定为view总宽度
        mCycleFactorW = (float) (2 * Math.PI / mTotalWidth);

        // 根据view总宽度得出所有对应的y值
        for (int i = 0; i < mTotalWidth; i++) {
            mYPositions[i] = (float) (STRETCH_FACTOR_A * Math.sin(mCycleFactorW * i) + OFFSET_Y);
        }
    }

    @Override
    protected void onDraw(Canvas canvas) {
        drawDefaultView(canvas);
        Path path = new Path();
        RectF oval1 = new RectF(0,0,getWidth(),getHeight());
        path.addArc(oval1,0,360);
        canvas.clipPath(path);

        // 从canvas层面去除绘制时锯齿
        canvas.setDrawFilter(mDrawFilter);
        resetPositonY();
        for (int i = 0; i < mTotalWidth; i++) {

            // 减400只是为了控制波纹绘制的y的在屏幕的位置，大家可以改成一个变量，然后动态改变这个变量，从而形成波纹上升下降效果
            // 绘制第一条水波纹
            canvas.drawLine(i, mTotalHeight - mResetOneYPositions[i] - 400, i,
                    mTotalHeight,
                    mWavePaint);

            // 绘制第二条水波纹
            canvas.drawLine(i, mTotalHeight - mResetTwoYPositions[i] - 400, i,
                    mTotalHeight,
                    mWavePaint);
        }

        // 改变两条波纹的移动点
        mXOneOffset += mXOffsetSpeedOne;
        mXTwoOffset += mXOffsetSpeedTwo;

        // 如果已经移动到结尾处，则重头记录
        if (mXOneOffset >= mTotalWidth) {
            mXOneOffset = 0;
        }
        if (mXTwoOffset > mTotalWidth) {
            mXTwoOffset = 0;
        }

        // 引发view重绘，一般可以考虑延迟20-30ms重绘，空出时间片
        postInvalidate();


    }

    private void drawDefaultView(Canvas canvas) {

        mCirclePaint.setStyle(Paint.Style.FILL);
        mCirclePaint.setColor(mContext.getResources().getColor(R.color.color));
        RectF oval1 = new RectF(0,0,getWidth(),getHeight());
        canvas.drawArc(oval1, 0, 360, false, mCirclePaint);

        canvas.drawText(secToTime(countdownTime), getWidth() / 2, getHeight()/4, timePaint);
    }

    private void resetPositonY() {
        // mXOneOffset代表当前第一条水波纹要移动的距离
        int yOneInterval = mYPositions.length - mXOneOffset;
        // 使用System.arraycopy方式重新填充第一条波纹的数据
        System.arraycopy(mYPositions, mXOneOffset, mResetOneYPositions, 0, yOneInterval);
        System.arraycopy(mYPositions, 0, mResetOneYPositions, yOneInterval, mXOneOffset);

        int yTwoInterval = mYPositions.length - mXTwoOffset;
        System.arraycopy(mYPositions, mXTwoOffset, mResetTwoYPositions, 0,
                yTwoInterval);
        System.arraycopy(mYPositions, 0, mResetTwoYPositions, yTwoInterval, mXTwoOffset);
    }

    public void start() {
        timeTimer.schedule(timeTask, 1000, 1000);
        curveTimer.schedule(curveTask,20,20);
    }

    public void setCountdownTime(int countdownTime) {
        this.countdownTime = countdownTime;
        postInvalidate();
    }

    public static int dip2px(Context context, float dpValue) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (dpValue * scale + 0.5f);
    }

    public void pause(){
        isPause = true;
    }

    public void resume(){
        isPause = false;
    }

    public void cancel() {
        timeTask.cancel();
        timeTimer.cancel();
        curveTimer.cancel();
        postInvalidate();
    }

    public static String secToTime(int time) {
        String timeStr = null;
        int hour = 0;
        int minute = 0;
        int second = 0;
        if (time <= 0)
            return "00:00";
        else {
            minute = time / 60;
            if (minute < 60) {
                second = time % 60;
                timeStr = unitFormat(minute) + ":" + unitFormat(second);
            } else {
                hour = minute / 60;
                if (hour > 99)
                    return "99:59:59";
                minute = minute % 60;
                second = time - hour * 3600 - minute * 60;
                timeStr = unitFormat(hour) + ":" + unitFormat(minute) + ":" + unitFormat(second);
            }
        }
        return timeStr;
    }

    public static String unitFormat(int i) {
        String retStr = null;
        if (i >= 0 && i < 10)
            retStr = "0" + Integer.toString(i);
        else
            retStr = "" + i;
        return retStr;
    }
}
